﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Media;
using System.Windows.Media.Media3D;
using Grafika_WPF.Components;

namespace Grafika_WPF.Shapes
{
    public class Cylinder : IShape
    {
        public Color Color { get; set; }

        public Point3D FirstCenter { get; set; }
        public Point3D SecondCenter { get; set; }

        public double R { get; set; }
        public Cylinder(Point3D firstCenter, Point3D secondCenter, double r, Color color)
        {

            FirstCenter = firstCenter;
            SecondCenter = secondCenter;
            Color = color;
            R = r;
            Triangles = new List<Triangle>();
        }


        public void Triangulate(int trianglesCount)
        {
            var triangles = new List<Triangle>();

            if (FirstCenter == SecondCenter)
                return;

            //Wysokość
            var hOriginal = FirstCenter - SecondCenter;
            //Wysokośc walca
            var hTemp = new Vector3D(0, hOriginal.Length, 0);

            //Liczba krokow
            double angleStep = 360.0 / trianglesCount;
            for (var i = 0; i < trianglesCount; i++)
            {
                var pStart = new Point3D(R, 0, 0);
                var rt = new RotateTransform3D();
                var r = new AxisAngleRotation3D(
                    new Vector3D(0, 1, 0),
                    i * angleStep);
                rt.Rotation = r;

                //3 pkt na dole
                var a1 = rt.Transform(pStart);
                r.Angle = (i + 1) * angleStep;
                var b1 = rt.Transform(pStart);
                var c1 = new Point3D(0, 0, 0);

                //3 pkt na gorze
                var a2 = a1 + hTemp;
                var b2 = b1 + hTemp;
                var c2 = c1 + hTemp;

                //trojkat na dole podstawy 
                triangles.Add(new Triangle { A = a1, B = b1, C = c1 });
                //trojkat na gorze podstawy
                triangles.Add(new Triangle { A = a2, B = b2, C = c2 });
                //trojkaty na scianie bocznej
                triangles.Add(new Triangle { A = a1, B = b1, C = a2 }); //trójkąt boczny 1
                triangles.Add(new Triangle { A = a2, B = b1, C = b2 });
            }


            //Obrót i translacja ze środka układu wsp.:
            double transformAngle = Vector3D.AngleBetween(hOriginal, hTemp);
            if (transformAngle != 0.0)
            {
                var rotateTransform = new RotateTransform3D();
                AxisAngleRotation3D rotation;

                //Jak rozny od 180 wykonujemy normalny obrot o kąt
                if (transformAngle != 180.0)
                    rotation = new AxisAngleRotation3D(
                        Vector3D.CrossProduct(hOriginal, hTemp),
                        transformAngle);
                else
                {
                    //wykonujemy obrot o 180
                    rotation = new AxisAngleRotation3D(
                        new Vector3D(1, 0, 0),
                        180.0);
                }
                rotateTransform.Rotation = rotation;

                //Trojkaty po obróceniu
                triangles = triangles.Select(x => new Triangle
                                                  {
                                                      A = rotateTransform.Transform(x.A),
                                                      B = rotateTransform.Transform(x.B),
                                                      C = rotateTransform.Transform(x.C)
                                                  }).ToList();
            }
            //Przesuniecie ze środka
            var translateTransform = new TranslateTransform3D(SecondCenter - new Point3D(0, 0, 0));

            triangles = triangles.Select(x => new Triangle
                                                  {
                                                      A = translateTransform.Transform(x.A),
                                                      B = translateTransform.Transform(x.B),
                                                      C = translateTransform.Transform(x.C),
                                                      Color = Color
                                                  }).ToList();
            Triangles = triangles;
        }

        public IList<Triangle> Triangles { get; set; }
    }


}
